<?php
include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'np_db_class.php';

class np_db_mysqli_singleton_class extends np_db_class
{
    private $m_conn = FALSE;
    private $m_query_res = FALSE;

    private $str_conn_key = '';
    private static $arr_conn_list = array();

    static $int_connect_count = 0;

    public function __construct($config)
    {
        $this->m_db_type = NP_DB_TYPE_MYSQL;
        $this->m_db_config = $config;
        $this->m_db_debug = array ();
        if (array_key_exists('db_log', $config))
        {
            $this->m_db_log = intval($config['db_log']);
        }
        $this->str_conn_key = $this->__get_conn_key();
    }

    private function _free_query_resource() {
        if (is_resource($this->m_query_res)) {
            mysqli_free_result($this->m_query_res);
            $this->m_query_res = FALSE;
        }
    }
    private function _close() {
        $this->_free_query_resource();
        if (is_resource($this->m_conn)) {
            mysqli_close($this->m_conn);
            $this->m_conn = FALSE;
        }

    }
    public function open()
    {
        // 释放资源和结果集
        $this->_close();

        // 判断连接是否已存在，如果已存在则直接使用，不需要再次创建数据库连接
        if (isset(self::$arr_conn_list[$this->str_conn_key]) && self::$arr_conn_list[$this->str_conn_key])
        {
            $this->m_conn = self::$arr_conn_list[$this->str_conn_key];
        }
        else
        {
            self::$int_connect_count++;
            $this->m_db_debug[] = array (
                'SQL'   => 'try to connect',
                'debug' => self::$int_connect_count,
                'time'  => date('Y-m-d H:i:s')
            );

            // 创建数据库连接
            $res_conn = new mysqli(
                $this->m_db_config['host'],
                $this->m_db_config['user'],
                $this->m_db_config['passwd'],
                $this->m_db_config['db_name']
            );
            if ($res_conn->connect_error)
            {
                die('Connect Error (' . $res_conn->connect_errno . ') ' . $res_conn->connect_error);
            }
            self::$arr_conn_list[$this->str_conn_key] = $res_conn;
            $this->m_conn = $res_conn;
        }
        $this->m_conn->query("SET NAMES utf8");
        return true;
    }
    public function close() {
        $this->_close();
        return TRUE;
    }

    private function _check_sql($sql) {
        $sql=trim($sql);
        if (isset ($this->m_db_config['mode']) && $this->m_db_config['mode'] == 'READ') {
            if (stripos($sql, 'insert') === 0 || stripos($sql, 'update') === 0 || stripos($sql, 'delete') === 0) {
                $this->error = "read mode not allow insert,update,delelte";
                return FALSE;
            }
        }

        return TRUE;
    }

    public function execute($sql) {
        if (!$this->_check_sql($sql))
            return FALSE;

        $this->_free_query_resource();

        if ($this->m_db_log & NP_DB_LOG_F_DUMP_CONN) {
            var_dump($this->m_conn);
        }
        if ($this->m_db_log & NP_DB_LOG_F_SQL) {
            var_dump($sql);
        }

        if ($this->m_conn == FALSE)
            return FALSE;

        $run_time=0;
        //		如果是调试模式,则开启时间记录 BYS67 2014-06-24
        if ($this->m_db_log & NP_DB_LOG_SQL_DEBUG_EXPLAIN)
        {
            np_runtime(FALSE);
        }


        $this->m_query_res = mysqli_query($this->m_conn,$sql);

        if ($this->m_db_log & NP_DB_LOG_SQL_DEBUG_EXPLAIN)
        {
            $run_time=np_runtime(TRUE);
        }


        if ($this->m_db_log & NP_DB_LOG_F_DUMP_RES) {
            var_dump($this->m_query_res);
        }

        if ($this->m_query_res === FALSE) {
            $this->m_db_debug[] = array (
                'SQL' => $sql,
                'debug' => $this->last_error_desc(),
                'time'=>$run_time
            );
            return FALSE;
        } else {
            $this->m_db_debug[] = array (
                'SQL' => $sql,
                'debug' => 'OK',
                'time'=>$run_time
            );
            return TRUE;
        }

        //		return TRUE;
    }
    public function query($sql) {
        if (!$this->_check_sql($sql))
            return FALSE;

        $this->_free_query_resource();

        if ($this->m_db_log & NP_DB_LOG_F_DUMP_CONN) {
            var_dump($this->m_conn);
        }
        if ($this->m_db_log & NP_DB_LOG_F_SQL) {
            var_dump($sql);
        }

        if ($this->m_conn === FALSE)
            return FALSE;

        $run_time=0;
        if ($this->m_db_log & NP_DB_LOG_SQL_DEBUG_EXPLAIN)
        {
            np_runtime(FALSE);
        }

        $this->m_query_res = mysqli_query($this->m_conn,$sql);
//		var_dump($this->m_query_res);die;

        if ($this->m_db_log & NP_DB_LOG_SQL_DEBUG_EXPLAIN)
        {
            $run_time=np_runtime(TRUE);

        }

        if ($this->m_db_log & NP_DB_LOG_F_DUMP_RES) {
            var_dump($this->m_query_res);
        }

        if ($this->m_query_res === FALSE) {


            $this->m_db_debug[] = array (
                'SQL' => $sql,
                'debug' => $this->last_error_desc(),
                'time'=>$run_time
            );
            return FALSE;
        } else {
            $explain_data='';
            if ($this->m_db_log & NP_DB_LOG_SQL_DEBUG_EXPLAIN)
            {
                //			记录索引使用情况
                $explain_data=$this->__get_debug_explain_sql($sql);
            }

            $this->m_db_debug[] = array (
                'SQL' => $sql,
                'debug' => 'OK',
                'time'=>$run_time,
                'explain_debug'=>$explain_data
            );
            return TRUE;
        }
        //			return FALSE;

        //		return TRUE;
    }
    public function get_query_result($is_free_after_get = TRUE) {
        if ($this->m_query_res === FALSE)
            return FALSE;

        //通锟斤拷锟斤拷锟斤拷模式
        $result = array ();

        while ($row = mysqli_fetch_assoc($this->m_query_res)) {
            $result[] = $row;
        }

        if ($is_free_after_get) {
            $this->_free_query_resource();
        }
        if ($this->m_db_log & NP_DB_LOG_F_DUMP_RESULT) {
            var_dump($result);
        }
        return $result;
    }
    public function last_error_no() {
        if ($this->m_conn == FALSE) {
            return mysqli_errno($this->m_conn);
        } else {
            return mysqli_errno($this->m_conn);
        }
    }
    public function affected_rows() {
        return mysqli_affected_rows($this->m_conn);
    }
    public function last_error_desc() {
        if (isset($this->error))
            return $this->error;
        if ($this->m_conn == FALSE) {
            return mysqli_error($this->m_conn);
        } else {
            return mysqli_error($this->m_conn);
        }
    }

    public function get_db_debug() {
        return $this->m_db_debug;
    }


    private function __get_debug_explain_sql($sql){
        if (stripos(trim($sql),'select')===0){
            $sql = 'explain '.$sql;
            $query_res = mysqli_query($this->m_conn,$sql);
            if ($query_res === FALSE) return FALSE;

            $result = array ();

            while ($row = mysqli_fetch_assoc($query_res)) {
                $result[] = $row;
            }

            if (is_resource($query_res)) {
                mysqli_free_result($query_res);
                unset($query_res);
            }
            return $result;
        }
        return FALSE;
    }

    public function get_db_config(){
        return $this->m_db_config;
    }

    private function __get_conn_key()
    {
        return md5(serialize($this->m_db_config));
    }
}